// permission 文件: 主要用来页面跳转时进行权限校验的, 可以在里面配置 路由守卫 钩子函数等
// 切换路由时就会执行 permission文件
// 具体封装的函数有:
// 1. request.js 封装axios, 里面书写拦截器
// 2. auth.js 封装的是 操作 cookie 的几个函数
// 3. get-page-title.js 封装的是操作页面标题的函数
// 4. validate 封装的是一些数据校验的函数
// 导入路由对象, 按需导入 动态路由对象
import router, { asyncRoutes } from '@/router'
import store from '@/store'
// 虚拟进度条: 开始进度条NProgress.start()  结束进度条NProgress.done()
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/get-page-title'

// 登录页面 不需要登录就可以访问，
// 白名单 ： 项目里面 不需要token，不需要登录既可以看见的页面  注册页  登录页面  404 等
const whiteList = ['/login', '/404']
// 判断一个元素 在不在 数组里面
//  arr.includes(xxx)    arr.indexOf(xxx) === -1

// 路由守卫， 2个函数---钩子函数， 在进入页面开始的时候自动执行
router.beforeEach(async(to, from, next) => {
  // 动态修改 title, 实现点击对应菜单标题, 切换网页的 标题
  // document.title = to.meta.title
  document.title = getPageTitle(to.meta.title)

  NProgress.start() // 开始进度条NProgress: 在路由守卫开启前, 开启进度条
  const token = store.state.user.token
  // console.log(token)
  // next()
  // 路由跳转判断， 先看有没有登录 （就是看有没有token值）
  if (token) {
    // if (to.path === '/login') {
    if (whiteList.includes(to.path)) {
      // 如果已经登录成功，还要去登录页面，用户体验就不好，应该直接给他跳转到首页
      next('/')
      NProgress.done()
    } else {
      // 当有token(用户已经登录), 并且要去的页面不是 login 时, 就发送请求获取用户信息数据
      // 这里必须要加 await 因为不加的话, 这个代码就不会等请求返回的结果, 直接走了 next, 代码逻辑就不对
      // 问题： 当用户已经登录后， 每次访问新的路由， 都会重新发送一次请求获取用户信息， 这样非常浪费性能
      // 解决方法：
      // 如果获取到了 userinfo 的数据, 就不要再发送请求了  ---  怎样才能知道请求成功了
      // 当我们请求成功后, 会将userInfo 中的数据存到 vuex 中
      // 此时可以进行一个判断，以 id 为例, vuex 里的数据 userInfo 有 id , 代表获取信息的请求已经发送过了, 否则就发送请求
      // 如果咩有发送过请求, 第一次进入页面跳转路由的时候, 执行的就是这里面的代码
      // 一个异步请求, 加上了 await 以后, 有没有返回值, 取决于异步方法里面, 有没有 return
      // 这里 dispatch 方法的返回值得到的是 vuex 中 actions函数的返回值
      if (!store.state.user.userInfo.id) {
        const res = await store.dispatch('user/getUserInfoActions')
        console.log('用户详细信息接口的返回值', res)
        const filterRoutes = asyncRoutes.filter(item => {
          const currentName = item.children[0].name
          return res.includes(currentName)
        })
        // 我们的动态路由就在这里进行添加
        // 下面代码写完之后, 动态路由在内存里面, 没有响应式的更新到左侧菜单
        // 为什么要在这里动态添加路由, 因为上面有请求,返回的值里面有用户具有的一些权限数组列表
        // 可以将 asyncRoutes动态路由 这个数组进行过滤
        // 比如 asyncRoutes动态路由数组 里面有 50 个元素, 也就是 50 个页面
        // 用户登录返回对应的权限以后, 在 50 个元素里面进行筛选, 然后再动态的加进去
        router.addRoutes(filterRoutes)
        // 然后, 将 * 匹配不到的路由, 添加到所有路由规则的最后面去
        // 不能放到中间, 因为之前我们在 vuex 中进行路由拼接的时候, 是吧静态路由和动态路由拼接了
        // 而在router/index.js文件中, 之前 * 路由是放在了静态路由最后面
        // 这样就会导致在静态路由与动态路由拼接时,  * 号路由就被拼接到了中间, 就会出现 bug, 刷新页面被跳转到首页了
        // 就是因为刷新后还没匹配到动态添加的路由, 就先匹配到了 * 路由
        // 解决方法就是: 在 筛选动态动态路由表 并 动态添加路由之后, 把 * 路由添加到最后面, 代表所有路由都匹配不到之后再进行通配符匹配路由
        filterRoutes.push({ path: '*', redirect: '/404', hidden: true })
        // 上面代码加载完以后, 只会在内存里面出现, 要访问页面只能手动输入
        // 想让左边菜单栏发生变化, 就需要将动态路由添加到 vuex 中, 这样就可以让动态路由响应式变化
        // 调用 store 对象上的 commit 方法, 将动态路由表作为参数传递给 mutations 函数修改 vuex 中的数据
        // 这样就可以让 路由表响应式的发生改变
        store.commit('menu/setMenuList', filterRoutes)
        // 如果当前页面是动态添加的路由, 在当前页面刷新的时候, 要么白屏, 要么是跳到首页
        next({
          ...to, // 动态添加的路由, 重新再进一遍
          replace: true // 将重新调整的动态路由的历史, 不要添加到路由的历史记录里面去
        })
      } else {
        next()
      }
    }
  } else {
    // 没有登录过的逻辑 （用户通过一些地址栏，强行跳转到其他页面，我们应该有个拦截的操作）
    // 如果没有 token , 证明用户未登录, 那么就再次进行判断
    // 如果用户没登录, 并且要去的页面不是登录页, 就强制跳转到登录页
    // 如果用户没有登陆, 并且要去的是登录页, 就放行
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login')
      NProgress.done()
    }
  }
})

// 进入页面以后执行的钩子函数 afterEach
// afterEach 并不一定都会执行， 如果在进入的beforeEach钩子函数里面
// 通过next('参数') 跳转到了其他页面(将正常的跳转方向给他改变了)，这个afterEach就不会执行
router.afterEach(() => {
  NProgress.done()
})

// 请你描述一下路由守卫？
